package top.alanshelby.utils;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * bean工厂
 */
public class BeanFactory {

    private List<BeanDefined> beanDefinedList; // 存放bean的集合

    private Map<String, Object> springIoc; // 存放已经创建好的实例对象（用于单例模式）

    public BeanFactory(List<BeanDefined> beanDefinedList) throws Exception {
        this.beanDefinedList = beanDefinedList;
        springIoc = new HashMap<String, Object>(); // 所有scope="singleton"采用单例模式管理bean对象
        for (BeanDefined bean : beanDefinedList) {
            if ("singleton".equals(bean.getScope())) {
                String classPath = bean.getClassPath();
                Class classFile = Class.forName(classPath);
                Object instance = classFile.newInstance();
                springIoc.put(bean.getBeanId(), instance);
            }
        }
    }

    /**
     * 获取bean实例
     *
     * @param beanId
     * @return
     * @throws Exception
     */
    public Object getBean(String beanId) throws Exception {
        Object instance = null;
        for (BeanDefined bean : beanDefinedList) {
            if (beanId.equals(bean.getBeanId())) {
                String classPath = bean.getClassPath();
                Class classFile = Class.forName(classPath);
                String scope = bean.getScope();
                String factoryBean = bean.getFactoryBean();
                String factoryMethod = bean.getFactoryMethod();
                if ("prototype".equals(scope)) {
                    /************ 动态工厂拓展 begin ************/
                    if (factoryBean != null && factoryMethod != null) {
                        // 用户希望指定工厂来创建实例对象
                        Object factoryObj = springIoc.get(factoryBean);
                        Class factoryClass = factoryObj.getClass();
                        Method methodObj = factoryClass.getDeclaredMethod(factoryMethod, null);
                        methodObj.setAccessible(true);
                        instance = methodObj.invoke(factoryObj, null);
                    } else {
                        // 如果scope是prototype（原型模式），每一次都创建一个新的实例对象
                        instance = classFile.newInstance();
                    }
                    /************ 动态工厂拓展 end ************/
                } else {
                    // 如果scope是singleton（单例模式），返回同一个实例对象
                    instance = springIoc.get(beanId);
                }
                return instance;
            }
        }
        return null;
    }

}
